#ifndef __TGRXBOILER_H__
#define __TGRXBOILER_H__

#if _MSC_VER > 1000
#pragma once
#endif

#define tgrx_abort(f) AfxMessageBox(_T(f))

#define TGRX_CLASS_APP				TGRX_COMPANY_CH "|" TGRX_HTTP

#define TGRX_DECLARE_MEMBERS(CLASS_NAME) \
	public: \
	virtual TGRxClass* isA() const; \
	static  TGRxClass* gpDesc; \
	static  TGRxClass* desc(); \
	static  CLASS_NAME* cast(const TGRxObject* inPtr) \
			{ \
				return ((inPtr == NULL) || !inPtr->isKindOf(CLASS_NAME::desc())) \
				? NULL : (CLASS_NAME*)inPtr; \
			}; \
	static void rxInit();

#define TGRX_DEFINE_MEMBERS(CLASS_NAME) \
	TGRxClass* CLASS_NAME::desc() \
	{ \
		if (CLASS_NAME::gpDesc != NULL) \
		return CLASS_NAME::gpDesc; \
		return CLASS_NAME::gpDesc \
		= (TGRxClass*)((TGRxDictionary*)rxSysRegistry() \
		->at(TGRX_CLASS_DICTIONARY))->at(#CLASS_NAME); \
	} \
	TGRxClass* CLASS_NAME::isA() const \
	{ \
		if (CLASS_NAME::gpDesc != NULL) \
		return CLASS_NAME::gpDesc; \
		return CLASS_NAME::gpDesc \
		= (TGRxClass*)((TGRxDictionary*)rxSysRegistry() \
		->at(TGRX_CLASS_DICTIONARY))->at(#CLASS_NAME); \
	} \
	TGRxClass* CLASS_NAME::gpDesc = NULL;

#define TGRX_STATIC_CHECK(CLASS_NAME) \
    if (CLASS_NAME::gpDesc) \
	{ \
		TGRxClass *pClass = \
		(TGRxClass*)((TGRxDictionary*)rxSysRegistry() \
		->at(TGRX_CLASS_DICTIONARY))->at(#CLASS_NAME); \
		if (pClass) \
		{ \
			if (CLASS_NAME::gpDesc == pClass) \
			return; \
			else \
			tgrx_abort(/*MSG*/"Class mismatch"); \
		} \
    }

#define TGRX_IMPLEMENT_DYNAMIC(CLASS_NAME,PARENT_CLASS,MDLVERSION,CLASS_VERSION,APP) \
		TGRX_DEFINE_MEMBERS(CLASS_NAME) \
		void CLASS_NAME::rxInit() \
		{ \
			TGRX_STATIC_CHECK(CLASS_NAME); \
			CLASS_NAME::gpDesc = newTGRxClass(#CLASS_NAME, #PARENT_CLASS, \
			MDLVERSION,CLASS_VERSION,-1, \
			NULL,APP); \
		}

#define TGRX_IMPLEMENT_NORMAL_DYNAMIC(CLASS_NAME,PARENT_CLASS) \
		TGRX_IMPLEMENT_DYNAMIC(CLASS_NAME,PARENT_CLASS,MDLCURRENTVER,0,TGRX_CLASS_APP)

#define TGRX_IMPLEMENT_DYNCREATE(CLASS_NAME,PARENT_CLASS,MDLVERSION,CLASS_VERSION,APP) \
		TGRX_DEFINE_MEMBERS(CLASS_NAME) \
		static TGRxObject * make##CLASS_NAME() { return new CLASS_NAME(); } \
		void CLASS_NAME::rxInit() \
		{ \
			TGRX_STATIC_CHECK(CLASS_NAME) \
			CLASS_NAME::gpDesc = newTGRxClass(#CLASS_NAME, #PARENT_CLASS, \
			MDLVERSION,CLASS_VERSION,-1, \
			&make##CLASS_NAME,APP); \
		}

#define TGRX_IMPLEMENT_NORMAL_DYNCREATE(CLASS_NAME,PARENT_CLASS) \
		TGRX_IMPLEMENT_DYNCREATE(CLASS_NAME,PARENT_CLASS,MDLCURRENTVER,0,TGRX_CLASS_APP)

#endif // __TGRXBOILER_H__